package org.example.managere.service.feibiao.impl;

import lombok.RequiredArgsConstructor;
import org.example.managere.dto.feibiao.AmArchivesFailureDto;
import org.example.managere.entity.feibiao.AmArchivesBase;
import org.example.managere.entity.feibiao.AmArchivesFailure;
import org.example.managere.repository.feibiao.AmArchivesBaseRepository;
import org.example.managere.repository.feibiao.AmArchivesFailureRepository;
import org.example.managere.service.feibiao.AmArchivesFailureService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 电机故障记录服务实现类
 */
@Service
@RequiredArgsConstructor
public class AmArchivesFailureServiceImpl implements AmArchivesFailureService {

    private final AmArchivesFailureRepository failureRepository;
    private final AmArchivesBaseRepository baseRepository;

    /**
     * 将实体转换为DTO
     */
    private AmArchivesFailureDto convertToDto(AmArchivesFailure failure) {
        AmArchivesFailureDto dto = new AmArchivesFailureDto();
        dto.setFailureId(failure.getFailureId());
        dto.setMotorId(failure.getMotorId().getMotorId());
        dto.setFailureTime(failure.getFailureTime());
        dto.setFailureType(failure.getFailureType());
        dto.setFailureCause(failure.getFailureCause());
        dto.setFailureDescription(failure.getFailureDescription());
        dto.setRepairTime(failure.getRepairTime());
        dto.setRepairMeasures(failure.getRepairMeasures());
        
        // 设置额外的显示字段
        dto.setMotorType(failure.getMotorId().getMotorType());
        dto.setManufacturer(failure.getMotorId().getManufacturer());
        
        return dto;
    }

    /**
     * 将DTO转换为实体
     */
    private AmArchivesFailure convertToEntity(AmArchivesFailureDto dto) {
        AmArchivesFailure entity = new AmArchivesFailure();
        
        if (dto.getFailureId() != null) {
            entity.setFailureId(dto.getFailureId());
        }
        
        // 查找关联的电机基本信息
        AmArchivesBase motorBase = baseRepository.findById(dto.getMotorId())
                .orElseThrow(() -> new IllegalArgumentException("电机ID不存在: " + dto.getMotorId()));
        
        entity.setMotorId(motorBase);
        entity.setFailureTime(dto.getFailureTime());
        entity.setFailureType(dto.getFailureType());
        entity.setFailureCause(dto.getFailureCause());
        entity.setFailureDescription(dto.getFailureDescription());
        entity.setRepairTime(dto.getRepairTime());
        entity.setRepairMeasures(dto.getRepairMeasures());
        
        return entity;
    }

    @Override
    @Transactional
    public AmArchivesFailureDto save(AmArchivesFailureDto amArchivesFailureDto) {
        AmArchivesFailure entity = convertToEntity(amArchivesFailureDto);
        AmArchivesFailure savedEntity = failureRepository.save(entity);
        return convertToDto(savedEntity);
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<AmArchivesFailureDto> findById(Integer failureId) {
        try {
            // 直接使用新增的DTO查询方法，避免懒加载问题
            return failureRepository.findDtoById(failureId);
        } catch (Exception e) {
            System.err.println("查询故障记录时发生错误: " + e.getMessage());
            e.printStackTrace();
            return Optional.empty();
        }
    }

    @Override
    @Transactional
    public AmArchivesFailureDto update(AmArchivesFailureDto amArchivesFailureDto) {
        // 确保记录存在
        if (amArchivesFailureDto.getFailureId() == null || 
                !failureRepository.existsById(amArchivesFailureDto.getFailureId())) {
            throw new IllegalArgumentException("无法更新不存在的记录，ID: " + amArchivesFailureDto.getFailureId());
        }
        
        AmArchivesFailure entity = convertToEntity(amArchivesFailureDto);
        AmArchivesFailure updatedEntity = failureRepository.save(entity);
        return convertToDto(updatedEntity);
    }

    @Override
    @Transactional
    public void deleteById(Integer failureId) {
        failureRepository.deleteById(failureId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<AmArchivesFailureDto> findAll() {
        try {
            // 使用分页查询所有数据，设置一个足够大的页面大小
            Pageable unpaged = Pageable.unpaged(); // 这将获取所有结果
            Page<AmArchivesFailureDto> page = failureRepository.findAllDto(unpaged);
            return page.getContent();
        } catch (Exception e) {
            System.err.println("查询所有故障记录时发生错误: " + e.getMessage());
            e.printStackTrace();
            return List.of(); // 返回空列表而不是抛出异常
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Page<AmArchivesFailureDto> findAll(Pageable pageable) {
        try {
            // 直接使用新增的DTO分页查询方法，避免懒加载问题
            return failureRepository.findAllDto(pageable);
        } catch (Exception e) {
            System.err.println("分页查询故障记录时发生错误: " + e.getMessage());
            e.printStackTrace();
            // 检查是否为懒加载相关错误
            String errorMsg = e.getMessage();
            if (errorMsg != null && (errorMsg.contains("could not initialize proxy") || errorMsg.contains("no session"))) {
                throw new RuntimeException("懒加载错误: 请确保查询中使用了DTO投影而不是实体对象: " + errorMsg, e);
            }
            throw new RuntimeException("查询故障记录失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public List<AmArchivesFailureDto> findByMotorId(String motorId) {
        try {
            // 直接使用新增的DTO查询方法，避免懒加载问题
            return failureRepository.findDtoByMotorId(motorId);
        } catch (Exception e) {
            System.err.println("根据电机ID查询故障记录时发生错误: " + e.getMessage());
            e.printStackTrace();
            return List.of(); // 返回空列表而不是抛出异常
        }
    }

    @Override
    @Transactional(readOnly = true)
    public List<AmArchivesFailureDto> findByFailureType(String failureType) {
        try {
            // 直接使用新增的DTO查询方法，避免懒加载问题
            return failureRepository.findDtoByFailureType(failureType);
        } catch (Exception e) {
            System.err.println("根据故障类型查询故障记录时发生错误: " + e.getMessage());
            e.printStackTrace();
            return List.of(); // 返回空列表而不是抛出异常
        }
    }

    @Override
    @Transactional(readOnly = true)
    public List<AmArchivesFailureDto> findByRepaired(Boolean repaired) {
        // 由于实体中没有 repaired 字段，我们可以基于 repairTime 是否为 null 来判断
        return failureRepository.findAll().stream()
                .filter(failure -> (repaired && failure.getRepairTime() != null) || 
                                  (!repaired && failure.getRepairTime() == null))
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }
} 